package com.atkxp.service.impl;

import com.atkxp.constant.AlgorithmStatus;
import com.atkxp.dto.req.TempScratchPaperDTO;
import com.atkxp.dto.req.UploadScratchPaperDTO;
import com.atkxp.dto.resp.AlgorithmDTO;
import com.atkxp.dto.resp.AlgorithmDescDTO;
import com.atkxp.dto.resp.Category;
import com.atkxp.dto.resp.ScratchPaperDescDTO;
import com.atkxp.entity.Algorithm;
import com.atkxp.entity.AlgorithmDescription;
import com.atkxp.mapper.AlgorithmMapper;
import com.atkxp.service.IAlgorithmService;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * @author longhunpomie - 蒯兴鹏
 * @declaration
 * @email 3314028177@qq.com
 * @create 2025/3/28-16:11
 */
@Service
public class AlgorithmServiceImpl implements IAlgorithmService {

    @Autowired
    private AlgorithmMapper algorithmMapper;

    @Override
    public List<Category> getAllCategory() {
        return algorithmMapper.getAllCategory();
    }

    @Override
    public List<AlgorithmDTO> getAllAlgorithmByCategory(String category) {
        return algorithmMapper.getAllAlgorithmByCategory(category);
    }

    @Override
    public String getDesc(String category, String algorithm) {
        return algorithmMapper.getDesc(category, algorithm);
    }

    @Override
    public List<AlgorithmDescDTO> getSimpleDesc(String category, String algorithm) {
        return algorithmMapper.getSimpleDesc(category, algorithm);
    }

    @Override
    public String getCode(String category, String algorithm, String file) {
        return algorithmMapper.getCode(category, algorithm, file);
    }

    @Override
    public String getData(String category, String algorithm, String file) {
        return algorithmMapper.getData(category, algorithm, file);
    }

    @Override
    public String getTemplate(String category, String algorithm, String file) {
        return algorithmMapper.getTemplate(category, algorithm, file);
    }

    @Override
    public String getScratchPaperData(Long userId, String file) {
        String data = algorithmMapper.getScratchPaperData(userId, file);
        if(StringUtils.isEmpty(data)) {
            return getDefaultData();
        }
        return data;
    }

    private String getDefaultData() {
        return "// 数据部分\n" +
                "const messages = [\n" +
                "  'Visualize',\n" +
                "  'your',\n" +
                "  'own',\n" +
                "  'code',\n" +
                "  'here!',\n" +
                "];\n" +
                "\n" +
                "// 可视化控件\n" +
                "const array2dTracer = new Array2DTracer('message');\n" +
                "const logTracer = new LogTracer('Console');\n" +
                "\n" +
                "\n" +
                "// 设置数据\n" +
                "array2dTracer._setData (messages);\n" +
                "logTracer._print(\"这是可视化部分:\");\n" +
                "\n";
    }

    @Override
    public String getScratchPaperCode(Long userId, String file) {
        String code = algorithmMapper.getScratchPaperCode(userId, file);
        if(StringUtils.isEmpty(code)) {
            return getDefaultCode();
        }
        return code;
    }

    private String getDefaultCode() {
        return "// 这里是可视化逻辑部分代码\n" +
                "function highlight(line) {\n" +
                "  if (line >= messages.length) return;\n" +
                "  const message = messages[line];\n" +
                "  logTracer._print(line + \":\" + message);\n" +
                "  array2dTracer._selectRow (line,  0, message.length - 1)._wait();\n" +
                "  array2dTracer._deselectRow (line, 0, message.length - 1)._wait();\n" +
                "  highlight(line + 1);\n" +
                "}\n" +
                "\n" +
                "highlight(0)\n" +
                "logTracer._print(\"可视化完成\")";
    }

    @Override
    public String getScratchPaperTemplate(Long userId, String file) {
        String template = algorithmMapper.getScratchPaperTemplate(userId, file);
        if(StringUtils.isEmpty(template)) {
            return getDefaultTemplate();
        }
        return template;
    }

    private String getDefaultTemplate() {
        return "#include<bits/stdc++.h>\n" +
                "\n" +
                "using namespace std;\n" +
                "\n" +
                "#define fi first\n" +
                "#define se second\n" +
                "#define int long long\n" +
                "#define alls(x) x.begin(), x.end()\n" +
                "#define pb push_back\n" +
                "#define end1n \" \\n\"[i == n]\n" +
                "#define endn1 \" \\n\"[i == 1]\n" +
                "#define endl '\\n'\n" +
                "\n" +
                "typedef long long ll;\n" +
                "typedef unsigned long long ull;\n" +
                "typedef pair<int, int> pii;\n" +
                "typedef pair<pii, int> piii;\n" +
                "typedef vector<int> vi;\n" +
                "typedef vector<pii> vpii;\n" +
                "typedef vector<vector<int>> vii;\n" +
                "const int N = 1e6 + 10;\n" +
                "const int mod = 1e9 + 7;\n" +
                "const int MAX = 1e18;\n" +
                "\n" +
                "void solve() {\n" +
                "    \n" +
                "}\n" +
                "\n" +
                "signed main() {\n" +
                "    ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);\n" +
                "    int t;\n" +
                "    cin >> t;\n" +
                "    // t = 1;\n" +
                "    while(t --) {\n" +
                "        solve();\n" +
                "    }\n" +
                "    return 0;\n" +
                "}";
    }

    @Override
    public String getScratchPaperDesc(Long userId) {
        return algorithmMapper.getScratchPaperDesc(userId);
    }

    @Override
    public List<ScratchPaperDescDTO> getScratchPaperSimpleDesc(Long userId) {
        return algorithmMapper.getScratchPaperSimpleDesc(userId);
    }

    @Override
    @Transactional
    public AjaxResult tempSaveScratchPaper(TempScratchPaperDTO data) {
        LoginUser loginUser = SecurityUtils.getLoginUser();
        SysUser user = loginUser.getUser();
        String markdown = data.getDesc();

        // 保存markdown内容
        if(StringUtils.isNotEmpty(algorithmMapper.getScratchPaperDesc(user.getUserId()))) {
            algorithmMapper.updateScratchPaperDesc(user.getUserId(), markdown);
        } else {
            algorithmMapper.insertScratchPaperDesc(user.getUserId(), markdown);
        }

        if(algorithmMapper.existScratchPaperFileByFileName(user.getUserId()) > 0) {
            algorithmMapper.deleteScratchPaperFile(user.getUserId());
        }
        // 保存代码功能
        List<TempScratchPaperDTO.Files> filesList = data.getFiles();
        for (TempScratchPaperDTO.Files files : filesList) {
            TempScratchPaperDTO.Files.File file = files.getFile();
            String fileName = files.getName();
            algorithmMapper.insertScratchPaperFile(user.getUserId(), fileName, files.getFileOrder(), file.getCode(), file.getData(), file.getTemplate(), file.getDesc());
        }
        return AjaxResult.success();
    }

    @Override
    @Transactional
    public AjaxResult uploadScratchPaper(UploadScratchPaperDTO data) {
        // 插入markdown部分
        algorithmMapper.insertAlgorithmDesc(new AlgorithmDescription(0l,
                data.getCategory(),
                data.getCategoryName(),
                data.getName(),
                data.getAlgorithmName(),
                AlgorithmStatus.AUDITING,
                data.getDesc()));

        List<TempScratchPaperDTO.Files> filesList = data.getFiles();
        for (TempScratchPaperDTO.Files files : filesList) {
            TempScratchPaperDTO.Files.File file = files.getFile();
            String fileName = files.getName();
            algorithmMapper.insertAlgorithm(new Algorithm(0l,
                    data.getCategory(),
                    data.getName(),
                    files.getName(),
                    files.getFileOrder(),
                    file.getDesc(),
                    file.getData(),
                    file.getCode(),
                    file.getTemplate()));
        }
        return AjaxResult.success();
    }

    @Override
    public List<Category> getAllReviewCategory() {
        return algorithmMapper.getAllReviewCategory();
    }

    @Override
    public List<AlgorithmDTO> getAllReviewAlgorithmByCategory(String category) {
        return algorithmMapper.getAllReviewAlgorithmByCategory(category);
    }

    @Override
    public AjaxResult onlineAlgorithm(String category, String name) {
        return AjaxResult.success(algorithmMapper.onlineAlgorithm(category, name));
    }

    @Override
    public AjaxResult refuseAlgorithm(String category, String name) {
        return AjaxResult.success(algorithmMapper.refuseAlgorithm(category, name));
    }
}
